package com.cwvs.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * 视频工具类.
 * 
 * @author mickey
 * 
 */
public class VideoUtil {
	/**
	 * 视频转码
	 * 
	 * @param ffmpegPath
	 *            转码工具的存放路径
	 * @param upFilePath
	 *            用于指定要转换格式的文件,要截图的视频源文件
	 * @param codcFilePath
	 *            格式转换后的的文件保存路径
	 * @param mediaPicPath
	 *            截图保存路径
	 * @param mencoder_home
	 *            mencoder路径地址
	 * @param tempFile_home
	 *            临时文件路径地址ffmpeg无法转换的视频路径
	 * @return
	 * @throws Exception
	 */
//	public static boolean executeCodecs(String ffmpeg_home,
//			String mencoder_home, String upFilePath, String codcFilePath,
//			String mediaPicPath, String temp) throws Exception {
//		tempFile_home = temp;
//		// 创建一个List集合来保存转换视频文件为flv格式的命令
//		List<String> convert = new ArrayList<String>();
//		convert.add(ffmpeg_home); // 添加转换工具路径
//		convert.add("-i"); // 添加参数＂-i＂，该参数指定要转换的文件
//		convert.add(upFilePath); // 添加要转换格式的视频文件的路径
//		convert.add("-qscale"); // 指定转换的质量
//		convert.add("6");
//		convert.add("-ab"); // 设置音频码率
//		convert.add("64");
//		convert.add("-ac"); // 设置声道数
//		convert.add("2");
//		convert.add("-ar"); // 设置声音的采样频率
//		convert.add("22050");
//		convert.add("-r"); // 设置帧频
//		convert.add("24");
//		convert.add("-y"); // 添加参数＂-y＂，该参数指定将覆盖已存在的文件
//		convert.add(codcFilePath);
//
//		// 创建一个List集合来保存从视频中截取图片的命令
//		List<String> cutpic = new ArrayList<String>();
//		cutpic.add(ffmpeg_home);
//		cutpic.add("-i");
//		cutpic.add(upFilePath); // 同上（指定的文件即可以是转换为flv格式之前的文件，也可以是转换的flv文件）
//		cutpic.add("-y");
//		cutpic.add("-f");
//		cutpic.add("image2");
//		cutpic.add("-ss"); // 添加参数＂-ss＂，该参数指定截取的起始时间
//		cutpic.add("17"); // 添加起始时间为第17秒
//		cutpic.add("-t"); // 添加参数＂-t＂，该参数指定持续时间
//		cutpic.add("0.001"); // 添加持续时间为1毫秒
//		cutpic.add("-s"); // 添加参数＂-s＂，该参数指定截取的图片大小
//		cutpic.add("225*251"); // 添加截取的图片大小为350*240
//		cutpic.add(mediaPicPath); // 添加截取的图片的保存路径
//
//		boolean mark = true;
//		ProcessBuilder builder = new ProcessBuilder();
//		try {
//			builder.command(convert);
//			builder.redirectErrorStream(true);
//			builder.start();
//
//			builder.command(cutpic);
//			builder.redirectErrorStream(true);
//			// 如果此属性为 true，则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并，
//			// 因此两者均可使用 Process.getInputStream() 方法读取。这使得关联错误消息和相应的输出变得更容易
//			builder.start();
//		} catch (Exception e) {
//			mark = false;
//			e.printStackTrace();
//		}
//		return mark;
//	}

	/**
	 * 功能函数
	 * 
	 * @param inputFile
	 *            待处理视频，需带路径
	 * @param outputFile
	 *            处理后视频，需带路径
	 * @return
	 */
	public static boolean convert(String ffmpeg_home, String mencoder_home,
			String inputFile, String outputFile,String mediaPicPath,String temp) {
		if (!checkfile(inputFile)) {
			return false;
		}
		if (process(ffmpeg_home, mencoder_home, inputFile, outputFile,mediaPicPath,temp)) {
			return true;
		}
		return false;
	}

	// private static boolean process() {
	// int type = checkContentType();
	// boolean status = false;
	// if (type == 0) {
	// status = processFLV(PATH);// 直接将文件转为flv文件
	// } else if (type == 1) {
	// String avifilepath = processAVI(type);
	// if (avifilepath == null)
	// return false;// avi文件没有得到
	// status = processFLV(avifilepath);// 将avi转为flv
	// }
	// return status;
	// }

	/**
	 * 检查视频类型
	 * 
	 * @param inputFile
	 * @return ffmpeg 能解析返回0，不能解析返回1
	 */
	private static int checkContentType(String inputFile) {
		String type = inputFile.substring(inputFile.lastIndexOf(".") + 1,
				inputFile.length()).toLowerCase();
		// ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
		if (type.equals("avi")) {
			return 0;
		} else if (type.equals("mpg")) {
			return 0;
		} else if (type.equals("wmv")) {
			return 0;
		} else if (type.equals("3gp")) {
			return 0;
		} else if (type.equals("mov")) {
			return 0;
		} else if (type.equals("mp4")) {
			return 0;
		} else if (type.equals("asf")) {
			return 0;
		} else if (type.equals("asx")) {
			return 0;
		} else if (type.equals("flv")) {
			return 0;
		}
		// 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等),
		// 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.
		else if (type.equals("wmv9")) {
			return 1;
		} else if (type.equals("rm")) {
			return 1;
		} else if (type.equals("rmvb")) {
			return 1;
		}
		return 9;
	}

	private static boolean checkfile(String path) {
		File file = new File(path);
		if (!file.isFile()) {
			return false;
		}
		return true;
	}

	// 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等), 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.
	// private static String processAVI(int type) {
	// List<String> commend = new java.util.ArrayList<String>();
	// commend.add("e:\\mencoder");
	// commend.add(PATH);
	// commend.add("-oac");
	// commend.add("lavc");
	// commend.add("-lavcopts");
	// commend.add("acodec=mp3:abitrate=64");
	// commend.add("-ovc");
	// commend.add("xvid");
	// commend.add("-xvidencopts");
	// commend.add("bitrate=600");
	// commend.add("-of");
	// commend.add("avi");
	// commend.add("-o");
	// commend.add("c:\\home\\a.avi");
	//
	// try {
	// ProcessBuilder builder = new ProcessBuilder();
	// builder.command(commend);
	// builder.start();
	// return "c:\\home\\a.avi";
	// } catch (Exception e) {
	// e.printStackTrace();
	// return null;
	// }
	// }

	/**
	 * 转换过程 ：先检查文件类型，在决定调用 processFlv还是processAVI
	 * 
	 * @param inputFile
	 * @param outputFile
	 * @return
	 */
	private static boolean process(String ffmpeg_home, String mencoder_home,
			String inputFile, String outputFile,String mediaPicPath,String temp) {
		int type = checkContentType(inputFile);
		boolean status = false;
		if (type == 0) {
			status = processFLV(ffmpeg_home, inputFile, outputFile,mediaPicPath);// 直接将文件转为flv文件
		} else if (type == 1) {
			String avifilepath = processAVI(mencoder_home, type, inputFile,temp);
			if (avifilepath == null)
				return false;// avi文件没有得到
			status = processFLV(ffmpeg_home, avifilepath, outputFile,mediaPicPath);// 将avi转为flv
		}
		return status;
	}

	/**
	 * ffmepg: 能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
	 * 
	 * @param inputFile
	 * @param outputFile
	 * @return
	 */
	private static boolean processFLV(String ffmpeg_home, String inputFile,
			String outputFile,String mediaPicPath) {
		if (!checkfile(inputFile)) {
			System.out.println(inputFile + " is not file");
			return false;
		}
		File file = new File(outputFile);
		if (file.exists()) {
			File media=new File(mediaPicPath);
			if(media.exists()){
				System.out.println("图片已经存在！无需转换");
			}else{
				// 创建一个List集合来保存从视频中截取图片的命令
				List<String> cutpic = new ArrayList<String>();
				cutpic.add(ffmpeg_home);
				cutpic.add("-i");
				cutpic.add(inputFile); // 同上（指定的文件即可以是转换为flv格式之前的文件，也可以是转换的flv文件）
				cutpic.add("-y");
				cutpic.add("-f");
				cutpic.add("image2");
				cutpic.add("-ss"); // 添加参数＂-ss＂，该参数指定截取的起始时间
				cutpic.add("17"); // 添加起始时间为第17秒
				cutpic.add("-t"); // 添加参数＂-t＂，该参数指定持续时间
				cutpic.add("0.001"); // 添加持续时间为1毫秒
				cutpic.add("-s"); // 添加参数＂-s＂，该参数指定截取的图片大小
				cutpic.add("225*251"); // 添加截取的图片大小为350*240
				cutpic.add(mediaPicPath); // 添加截取的图片的保存路径
				try {
					ProcessBuilder builder = new ProcessBuilder();
					builder.command(cutpic);
					builder.start();
					builder.redirectErrorStream(true);
					return true;
				} catch (Exception e) {
					e.printStackTrace();
					return false;
				}
			}
			System.out.println("flv文件已经存在！无需转换");
			return true;
		} else {
			System.out.println("正在转换成flv文件……");

			List<String> commend = new java.util.ArrayList<String>();
			// 低精度
			commend.add(ffmpeg_home);
			commend.add("-i");
			commend.add(inputFile);
			commend.add("-ab");
			commend.add("128");
			commend.add("-acodec");
			commend.add("libmp3lame");
			commend.add("-ac");
			commend.add("1");
			commend.add("-ar");
			commend.add("22050");
			commend.add("-r");
			commend.add("29.97");
			// 清晰度 -qscale 4 为最好但文件大, -qscale 6就可以了
			commend.add("-qscale");
			commend.add("4");
			commend.add("-y");
			commend.add(outputFile);
			
			// 创建一个List集合来保存从视频中截取图片的命令
			List<String> cutpic = new ArrayList<String>();
			cutpic.add(ffmpeg_home);
			cutpic.add("-i");
			cutpic.add(inputFile); // 同上（指定的文件即可以是转换为flv格式之前的文件，也可以是转换的flv文件）
			cutpic.add("-y");
			cutpic.add("-f");
			cutpic.add("image2");
			cutpic.add("-ss"); // 添加参数＂-ss＂，该参数指定截取的起始时间
			cutpic.add("17"); // 添加起始时间为第17秒
			cutpic.add("-t"); // 添加参数＂-t＂，该参数指定持续时间
			cutpic.add("0.001"); // 添加持续时间为1毫秒
			cutpic.add("-s"); // 添加参数＂-s＂，该参数指定截取的图片大小
			cutpic.add("225*251"); // 添加截取的图片大小为350*240
			cutpic.add(mediaPicPath); // 添加截取的图片的保存路径
			
			StringBuffer test = new StringBuffer();
			for (int i = 0; i < commend.size(); i++)
				test.append(commend.get(i) + " ");
			try {
				ProcessBuilder builder = new ProcessBuilder();
				builder.command(commend);
				builder.start();
				builder.command(cutpic);
				builder.start();
				//builder.redirectErrorStream(true);
				return true;
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}

		}

	}

	/**
	 * Mencoder:
	 * 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等),可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.
	 * 
	 * @param type
	 * @param inputFile
	 * @return
	 */
	private static String processAVI(String mencoder_home, int type,
			String inputFile,String temp) {
		File file = new File(temp);
		if (file.exists()) {
			System.out.println("avi文件已经存在！无需转换");
			return temp;
		}
		List<String> commend = new java.util.ArrayList<String>();
		commend.add(mencoder_home);
		commend.add(inputFile);
		commend.add("-oac");
		commend.add("mp3lame");
		commend.add("-lameopts");
		commend.add("preset=64");
		commend.add("-ovc");
		commend.add("xvid");
		commend.add("-xvidencopts");
		commend.add("bitrate=600");
		commend.add("-of");
		commend.add("avi");
		commend.add("-o");
		commend.add(temp);
		StringBuffer test = new StringBuffer();
		for (int i = 0; i < commend.size(); i++)
			test.append(commend.get(i) + " ");
		System.out.println(test);
		try {
			ProcessBuilder builder = new ProcessBuilder();
			builder.command(commend);
			Process p = builder.start();
			/**
			 * 清空Mencoder进程 的输出流和错误流 因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小，
			 * 如果读写子进程的输出流或输入流迅速出现失败，则可能导致子进程阻塞，甚至产生死锁。
			 */
			final InputStream is1 = p.getInputStream();
			final InputStream is2 = p.getErrorStream();
			new Thread() {
				public void run() {
					BufferedReader br = new BufferedReader(
							new InputStreamReader(is1));
					try {
						String lineB = null;
						while ((lineB = br.readLine()) != null) {
							if (lineB != null)
								System.out.println(lineB);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}.start();
			new Thread() {
				public void run() {
					BufferedReader br2 = new BufferedReader(
							new InputStreamReader(is2));
					try {
						String lineC = null;
						while ((lineC = br2.readLine()) != null) {
							if (lineC != null)
								System.out.println(lineC);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}.start();

			// 等Mencoder进程转换结束，再调用ffmpeg进程
			p.waitFor();
			System.out.println("who cares");
			return temp;
		} catch (Exception e) {
			System.err.println(e);
			return null;
		}
	}

	// ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
	// private static boolean processFLV(String oldfilepath) {
	//
	// if (!checkfile(PATH)) {
	// System.out.println(oldfilepath + " is not file");
	// return false;
	// }
	//
	// List<String> commend = new java.util.ArrayList<String>();
	// commend.add("e:\\ffmpeg");
	// commend.add("-i");
	// commend.add(oldfilepath);
	// commend.add("-ab");
	// commend.add("64");
	// commend.add("-acodec");
	// commend.add("mp3");
	// commend.add("-ac");
	// commend.add("2");
	// commend.add("-ar");
	// commend.add("22050");
	// commend.add("-b");
	// commend.add("230");
	// commend.add("-r");
	// commend.add("24");
	// commend.add("-y");
	// commend.add("c:\\home\\a.flv");
	// try {
	// ProcessBuilder builder = new ProcessBuilder();
	// builder.command(commend);
	// builder.start();
	// return true;
	// } catch (Exception e) {
	// e.printStackTrace();
	// return false;
	// }
	//
	// }

	/**
	 * 路径拼接.
	 * 
	 * @param root
	 *            以‘/’结尾.
	 * @param relativeUrl
	 * @return
	 */
	public static String pathCat(String root, String relativeUrl) {
		if (StringUtils.isBlank(relativeUrl)) {
			relativeUrl = "";
		}
		if (relativeUrl.startsWith("/")) {
			relativeUrl = relativeUrl.substring(1);
		}

		StringBuilder ret = new StringBuilder();
		ret.append(root);
		ret.append(relativeUrl);
		return ret.toString();
	}

	/**
	 * 确保斜杠结尾 ^_^
	 * 
	 * @return
	 */
	public static String quebao_xiekang_jiewei(String path) {
		if (StringUtils.isBlank(path)) {
			return "/";
		}
		if (path.endsWith("/")) {
			return path;
		} else {
			return path + "/";
		}
	}
}
